#a guessing game where a number 1 through 10 is generated and the user gets 3 tries to guess

#Fine imports
import random
import os

#
#
#
############################
#debug show number toggle
debug = 0
##########################################
### Stores Messages
class Message:
        #Message storage
        block = """
______                _                   _   _                 _               
| ___ \              | |                 | \ | |               | |              
| |_/ /__ _ _ __   __| | ___  _ __ ___   |  \| |_   _ _ __ ___ | |__   ___ _ __ 
|    // _` | '_ \ / _` |/ _ \| '_ ` _ \  | . ` | | | | '_ ` _ \| '_ \ / _ \ '__|
| |\ \ (_| | | | | (_| | (_) | | | | | | | |\  | |_| | | | | | | |_) |  __/ |   
\_| \_\__,_|_| |_|\__,_|\___/|_| |_| |_| \_| \_/\__,_|_| |_| |_|_.__/ \___|_|   

        
 _____                                                                          
|  __ \                                                                         
| |  \/ __ _ _ __ ___   ___                                                     
| | __ / _` | '_ ` _ \ / _ \                                                    
| |_\ \ (_| | | | | | |  __/                                                    
 \____/\__,_|_| |_| |_|\___|   """              
        intro = "WELCOME! I have right here a number.\nYou have some tries to guess it!"


############ All three print messages
        def open(self):
                print(self.block)
                print(self.intro)
### These next Two print random messages for the situation

class Menu:
        state = 0
        command ={'1':1,'Play':1,'play':1,'quit':666,'Quit':666,'QUIT':666,'score':3,'Score':3,'Q':666,'2':3,'q':666,'8':8,'9':9,'difficulty':4,'Difficulty':4,'4':4,'5':5,'6':6}
        
        
        intmenu = "Do you want to Play? (1/Play) Quit? (Q/Quit) \nView the High Score? (2/Score) or change difficulty? (4/Difficulty)\n OR try the new secret Rock Paper Scissors mode (5 to turn on, 6 to turn off)"

        def display(self):
                # Displays the menu choices
                
                
                print(self.intmenu)
                
        def ginput(self):
                #gets user choice
                letter = input("Choice: ")
                while letter not in self.command:
                        letter = input("Choice: ")
                self.state = self.command[letter]
        def returntomenu(self):
                #Brings us back to the menu
              
                self.state = 0
                return self.state


class Scoring:
        #Scoring is High score board stored to file
        name = "LMN"
        wins = []
        currentsco = 0
        diffibonus = 0
        hardmenu ={'Normal':0,'Hard':1,'More Hard':2,'Psychic':3}
        diffiname = "Normal"
        def __init__(self):
                #opens save file if it exists, makes it if it doesn't
                if os.path.isfile('./score0.sav'):
                        print('OPENING OLD SAV')
                        sav = open('score0.sav','r')
                        intlist = sav.readlines()
                        for line in intlist:
                                x = line.strip('\n').split(':')
                
                                self.wins.append([x[0],int(float(x[1]))])
                        sav.close()
                else:
                        print('WRITING NEW FILE')
                        sav = open('score0.sav','w')
                        for pair in self.wins:
                
                                sav.write(pair[0] + ":" + str(pair[1]) + "\n")
                        sav.close()
        def getnam(self):
                #Gets the name for scoring
                self.name = str(input("What is your name? "))
        def scointro(self):
                print("""
Choose a difficulty!
"Normal"             3 tries and between 1 and 3
"Hard"               3 tries and between 1 and 10
"More Hard"          2 tries and betwen 1 and 20
"Psychic"            1 try and between 1 and 100!

Each difficulty adds extra points for guessing right!
And Type it exactly! No quotes!

""")
        def setdifficultybonus(self):
        
                #gets user choice
                letterd = input("Choice: ")
                while letterd not in self.hardmenu:
                        letterd = input("Choice: ")
                self.diffibonus = self.hardmenu[letterd]
                self.diffiname = letterd
        def viewdifficulty(self):
                #prints the difficulty
                print("The difficulty is at: " + self.diffiname)
        def addscore(self):
                #adds to the score 
                self.currentsco += 1
                self.currentsco += self.diffibonus
        def writescore(self):
                #a manual write to file just in case
                print('WRITING TO FILE')
                sav = open('testscore0.sav','w')
                for pair in self.wins:
                        
                        sav.write(pair[0] + ":" + str(pair[1]) + "\n")
            
                sav.close()
                return self.wins
        def viewscore(self):
                #prints the current score and scoreboard
                print ("Your Current Score is: " , self.currentsco)
                print("previous winners:\n")
                for score in self.wins:
                        print("Player: " , score[0] , "   Score: " , score[1])
        def losereset(self):
                #resets the score on loss (or quit) and writes it
                if self.currentsco != 0:
                        self.wins.append([self.name,self.currentsco])
                        print("The score is reset!")
                self.currentsco = 0
                print('WRITING TO FILE')
                sav = open('score0.sav','w')
                for pair in self.wins:
                        
                        sav.write(pair[0] + ":" + str(pair[1]) + "\n")
                sav.close()

class Guessing:

        #Heart of the guessing game
        FirstGuess = "Tell me what you think the number is?"
        victorymsg = 'You did it!', 'Congratulations!', 'You won!', 'Victory!'

        gameover = 'You tried your best! \nBut.... this is a guessing game so you really couldn\'t do much', 'Sorry, all those guesses are wrong :(', 'All were wrong, try again later!'
        retry = 'Hmm... \n*checks notes* \nThat number is wrong. \nTry again!', 'You go \nSorry, I read that wrong. \nYou didn\'t get it right. \nTry again.', 'Aww. Wrong number.\nTry again!'
        lasttry = 'One more time!\nYou can do it!', 'IT IS THE FINAL ROUND OF THE MATCH!\nFIGHT!', 'This is your last chance!\nWhat is your guess?'
        maxtries = 3
        tries = 0
        answer = 0
        rangetop = 10
        difficultrang = {0:3,1:10,2:20,3:100}
        difficulttry = {0:3,1:3,2:2,3:1}
        rando = 0
        rockinans = 0
        rockinmirror = {1:'Rock',2:'Paper',3:'Scissors'}
        rockinchoice = {'rock':1,'1':1,'2':2,'3':3,'Rock':1,'paper':2,'Paper':2,'Scissors':3,'scissors':3}
        def __init__(self,type,inps):
                self.type = type
                #sets difficulty stuff
                self.maxtries = self.difficulttry[inps]
                self.rangetop = self.difficultrang[inps]
                if self.type == "rps":
                        self.maxtries = 1
                        self.rangetop = 3
                #generates random number 1 to range
                self.rando = random.randint(1,self.rangetop)
                self.tries = 0
        def oneguess(self):
                if mode == "rps":
                        print("RPS?")
                else:
                        print(self.FirstGuess)
                                
        def gover(self):
                if self.type == "rps":
                        print ("Aww.. You lost")
                else:
                        print(random.choice(self.gameover))
        def trymsg(self):
                if self.maxtries == 3 and self.tries == 1:
                        print(random.choice(self.retry))
                if self.tries == self.maxtries -1:
                        print(random.choice(self.lasttry))

        def win(self):
                
                print(random.choice(self.victorymsg))

                if self.type == "rps":
                        print("Your opponent chose: ", self.rockinmirror[self.rando])
        
        def showtries(self):
                #shows the tries
                print(self.maxtries)
        def settries(self):
                #custom input for # of tries, might be used for custom game stuff
                tries = input("Tries: ")
        def getanswer(self):
                if self.type == "rps":
                               
                        #gets user choice
                        rockinput = input("Rock(1), Paper(2), or Scissors(3)? ")
                        while rockinput not in self.rockinchoice:
                                rockinput = input("Choice: ")
                        self.rockinans = self.rockinchoice[rockinput]
                else:
                        #gets an answer from user and checks if it is valid (within range and an int)
                        self.answer=199 #hack
                        while not (self.answer <=self.rangetop and self.answer >=0):
                                answer = input("My answer is: ")
                                if answer.isdigit():
                                        self.answer= int(answer)

              
        def checkanswer(self):
                if self.type == "rps":
                        if self.rockinans == self.rando:
                                #print("Tie!")
                                
                                return False
                
                        if self.rockinans == 1 and self.rando == 3:
                                return True
                        if self.rockinans == 2 and self.rando == 1:
                                return True
                        if self.rockinans == 3 and self.rando == 2:
                                return True
                        else:
                                return False
                        
                else:
                        #checks if the answer is the random number
                        if self.answer == self.rando:
                                return True
                        else:
                                return False

        def checktries(self):
               # checks if you answered too many times
                if self.tries == self.maxtries:
                        return True
                if self.tries < self.maxtries:
                        return False
                
        def addtry(self):
                if self.type == "rps":
                        if self.rockinans == self.rando:
                                self.tries = 0
                                print("Tie!")
                                self.rando = random.randint(1,self.rangetop)
                        else:
                                self.tries +=1
                #adds a try each time you try.. and FAIL
                else:
                        self.tries += 1
        def viewwinticket(self):
                if self.type == "rps":
                        print("Your opponent chose: ", self.rockinmirror[self.rando])
                        
                else:
                        print("The number was:", self.rando)

        def checkend(self):
                #### checks if it should end the loop or not and go to an end. debug print below
                
                #print(self.answer,self.rando,self.tries,self.maxtries)
                if self.answer == self.rando or self.tries >= self.maxtries:
                        return True
                        
                else:
                        return False

#######   main code !!!!!!!!!!!!!!!!!!!##############################
#declares objects n' stuff
hiscore = Scoring()
intro = Message()
mmenu = Menu()
mode = "guess"
intmenu = mmenu.intmenu
wins = 0
hiscore.getnam()
intro.open()
hiscore.scointro()
hiscore.setdifficultybonus()
while 1:
        while mmenu.state == 0:
        
                #main menu loop
                if debug == 1:
                        print(mmenu.state)
                hiscore.viewdifficulty()
                mmenu.display()
                mmenu.ginput()
                if debug == 1:
                        print(mmenu.state)
                if mmenu.state == 3:
                        #highscore
                
                        
                        hiscore.viewscore()
                        mmenu.returntomenu()
                if mmenu.state == 4:
                        #difficulty changer
                        hiscore.scointro()
                        hiscore.setdifficultybonus()
                        mmenu.returntomenu()
        #### Debug toggle
                if mmenu.state == 9:
                        print("debug on")
                        debug = 1
                        mmenu.returntomenu()
                if mmenu.state == 8:
                        print("debug off")
                        debug = 0
                        mmenu.returntomenu()
        #### RPS toggle ##
                if mmenu.state == 5:
                        print("secret RPS mode on")
                        mode = "rps"
                        mmenu.returntomenu()
                if mmenu.state == 6:
                        print("secret RPS mode off")
                        mode = "guess"
                        mmenu.returntomenu()
        
        if mmenu.state == 1:
#################### main game loop zone

                newgame = Guessing(mode,hiscore.diffibonus)
                newgame.oneguess()
                if debug == 1:
                        print(newgame.rando)
                #newgame.getdifficult(hiscore.diffibonus)
                #newgame.getrando()
                newgame.getanswer()

                newgame.addtry()
                ############# asks more here
                while not  newgame.checkend():


                        newgame.trymsg()
                        newgame.getanswer()
	                
                        newgame.addtry()
                #win/lose if/else stuff
                if newgame.checkanswer():
                        
                        hiscore.addscore()
                        newgame.win()
                        mmenu.returntomenu()
                elif newgame.checktries():

                        newgame.gover()

                        newgame.viewwinticket()
                        hiscore.losereset()
                        mmenu.returntomenu()
                else:
                        print("this shouldn't happen")
        
                del newgame #deltes game object

        if mmenu.state == 666:
                ##quitter
                hiscore.losereset()
                print("Bye!")
                quit()

#


